/**
 * Copyright 1998-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
 * All rights reserved.
 */
package ca.uvic.cs.cogz.mapping.filter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;

import ca.uvic.cs.cogz.mapping.core.MappingTypeManager.MappingType;
import ca.uvic.cs.cogz.mapping.filter.TreeFilterManager.TreeFilterType;
import ca.uvic.cs.cogz.mapping.ontology.DataLoaderFacade;
import ca.uvic.cs.cogz.util.TreeUtil;
import edu.stanford.smi.protege.model.Cls;
import edu.stanford.smi.protege.model.Frame;
import edu.stanford.smi.protege.model.KnowledgeBase;

/**
 * Implementation of a ITreeSearchBasedFilter. Used for finding all the mappings of a given type in
 * an ontology.
 * 
 * @author Sean Falconer
 * @date 10-Jan-07
 */
public class MappedItemFilter implements ITreeSearchBasedFilter {
	private int treeIndex;
	private HashSet<Cls> searchResults;
	private MappingType[] mappingTypes;

	public MappedItemFilter() {
		searchResults = new HashSet<Cls>();
		mappingTypes = new MappingType[2];
	}

	public void setTreeIndex(int treeIndex) {
		this.treeIndex = treeIndex;
	}

	public MappingType getMappingType() {
		if (treeIndex >= 0 && treeIndex < mappingTypes.length) {
			return mappingTypes[treeIndex];
		}

		return null;
	}

	public void setMappingType(MappingType mappingType) {
		mappingTypes[treeIndex] = mappingType;
	}

	@SuppressWarnings("unchecked")
	public Collection<Collection> performSearch(KnowledgeBase kb) {
		Collection<Frame> results = null;
		searchResults.clear();

		Map<Frame, MappingType> frameToMappingType;
		if (treeIndex == TreeFilterManager.SOURCE_SEARCH) {
			frameToMappingType = DataLoaderFacade.getInstance().getMappingCollection().getSourceFrames();
		} else {
			frameToMappingType = DataLoaderFacade.getInstance().getMappingCollection().getTargetFrames();
		}
		results = frameToMappingType.keySet();
		HashSet<Collection> matchedPaths = new HashSet<Collection>(results.size());

		for (Frame searchHit : results) {
			MappingType frameMappingType = frameToMappingType.get(searchHit);
			// TODO : may need to change the Cls check
			if (searchHit instanceof Cls && frameMappingType.equals(getMappingType())) {
				Cls clsItem = (Cls) searchHit;

				searchResults.add(clsItem);
				searchResults.addAll(clsItem.getSuperclasses());

				ArrayList<Frame> currentPath = new ArrayList<Frame>();
				TreeUtil.buildObjectPaths(clsItem, currentPath, matchedPaths, true);
			}
		}

		return matchedPaths;
	}

	/**
	 * Checks to see if the frame is an actual mapped item. This is different than isMatch, which
	 * includes ancestors of mapped frames.
	 */
	public boolean isExactMatch(Frame frame) {
		Collection<Frame> results = null;
		if (treeIndex == TreeFilterManager.SOURCE_SEARCH) {
			results = DataLoaderFacade.getInstance().getMappingCollection().getSourceFrames().keySet();
		} else {
			results = DataLoaderFacade.getInstance().getMappingCollection().getTargetFrames().keySet();
		}

		return results.contains(frame);
	}

	/**
	 * Checks to see if any of the search results match the given frame.
	 */
	public boolean isMatch(Frame frame) {
		return isActive() && searchResults.contains(frame);
	}

	public boolean isActive() {
		return searchResults.size() > 0;
	}

	public void reset() {
		searchResults.clear();
	}

	public TreeFilterType getType() {
		return TreeFilterType.MAPPED_ITEM_FILTER;
	}
}
